package Collections;

import java.util.Arrays;

/**
 * Created by eason on 2017/10/4.
 */
public class MyArrayList<E> {
    /**默认的初始化 10**/
    private static final int DEFAULT_CAPACITY = 10;
    /***空实例***/
    private static final Object[] EMPTY_ELEMENTDATA = {};
    /**空实例**/
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /***Array存放值得载体(容器)是一个Object数据，意味着任何类型值均可放入***/
    transient Object[] elementData;
    /***ArrayList的长度****/
    private int size;
    // ArrayList  modCount是由ArrayList 从AbstractList中继承过来的
    //The number of times this list has been <i>structurally modified</i>
    protected transient int modCount = 0;
    /***
     * 可以设置初始化大小的构造函数 大小 为initialCapacity的object数组
     * @param initialCapacity
     */
    public MyArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
    }

    /**
     * 构造函数 空参 默认初始化大小为0的空object数组
     */
    public MyArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = e; //存放新加进来的值
        return true;
    }

    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY;
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //判断原先数组 是否为空 为空最小容量则为10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    /***
     * minCapacity 保证add正常添加不会越界
     * @param minCapacity
     */
    private void ensureExplicitCapacity(int minCapacity) {
        //修改计数(这里是扩容)
        modCount++;

        // overflow-conscious code
        //判断现在的数组大小需不需要扩容 minCapacity 的意义在于保证下一步有数据add时至少有一空间可以使用
        //minCapacity在 add方法中时size+1也就是说，时ArrayList当前长度+1
        // 也就是要保证object数组 必须要大于实际存放在它的数据（ArrayList）的长度
        if (minCapacity - elementData.length > 0)  //存放值得数组保证Arralist正常使用所必需的的最小容量 -数组当前容量
            grow(minCapacity);
    }
    //数组最大值
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /***
     * 数组扩容，
     * @param minCapacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); //新数组容量 为原来为扩容前的1.5倍 若 oldCapacity =10  newCapacity为15
        if (newCapacity - minCapacity < 0)  //新扩容的数组容量 最小容量 则新数组容量大小置为minCapacity 保证可以有空间可以添加
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0) //保证不超过最大容量
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity); //数组扩容，切将原先数组所存放的值转移到新数组
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

    public int size() {
        return size;
    }
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

    E elementData(int index) {
        return (E) elementData[index];
    }

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }
}
